package com.jimo.get_network_state

import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.annotation.RequiresApi
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.EventChannel.StreamHandler

class GetNetworkStatePlugin : FlutterPlugin, MethodCallHandler, StreamHandler {
  private var eventSink: EventChannel.EventSink? = null
  private lateinit var eventChannel: EventChannel
  private lateinit var connectivityManager: ConnectivityManager
  private lateinit var channel: MethodChannel
  private val networkCallback = @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
  object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network: Network) {
      super.onAvailable(network)
      Handler(Looper.getMainLooper()).post {
        eventSink?.success(true)
      }
    }
    override fun onLost(network: Network) {
      super.onLost(network)
      Handler(Looper.getMainLooper()).post {
        eventSink?.success(false)
      }
    }
  }
  override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    connectivityManager =
      flutterPluginBinding.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "get_network_state")
    eventChannel = EventChannel(flutterPluginBinding.binaryMessenger, "get_network_state_events")
    channel.setMethodCallHandler(this)
    eventChannel.setStreamHandler(this)
  }

  override fun onMethodCall(call: MethodCall, result: Result) {
    when (call.method) {
      "getNetWorkState" -> {
        result.success(isNetworkAvailable())
      }
      "startMonitoring" -> {
        startMonitoring()
        result.success("")
      }
      "stopMonitoring" -> {
        stopMonitoring()
        result.success("")
      }
      "init" -> {
        result.success("")
      }
      else -> {
        result.notImplemented()
      }
    }
  }

  private fun startMonitoring() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
      connectivityManager.registerDefaultNetworkCallback(networkCallback)
    }
  }

  private fun stopMonitoring() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
      connectivityManager.unregisterNetworkCallback(networkCallback)
    }
  }

  override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)
    eventChannel.setStreamHandler(null)
  }

  private fun isNetworkAvailable(): Boolean {
    val activeNetworkInfo = connectivityManager.activeNetworkInfo
    return activeNetworkInfo != null && activeNetworkInfo.isConnected
  }

  override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
    this.eventSink = events
  }

  override fun onCancel(arguments: Any?) {
    eventSink = null
  }
}

